package wavelinkrobot;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;

import org.apache.xml.utils.PrefixResolverDefault;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.google.wave.api.AbstractRobotServlet;
import com.google.wave.api.Annotation;
import com.google.wave.api.Blip;
import com.google.wave.api.Element;
import com.google.wave.api.Event;
import com.google.wave.api.EventType;
import com.google.wave.api.Range;
import com.google.wave.api.RobotMessageBundle;
import com.google.wave.api.TextView;

@SuppressWarnings("serial")
public class WaveLinkRobotServlet extends AbstractRobotServlet {
	public static final String searchURLprefix = "http://www.wowhead.com/?item=";
	public static final String searchURLsuffix = "&xml";
	private static final Logger log = Logger.getLogger(WaveLinkRobotServlet.class.getName());
	public void dumpAnnotations(Blip blip) {
		TextView document = blip.getDocument();
		List<Annotation> annotations = document.getAnnotations();
		for (Annotation annotation : annotations) {
			System.err.println("name " + annotation.getName() + " value " +annotation.getValue());
		}
		List<Element> elements = document.getElements();
		for (Element element : elements) {
			System.err.println(element.toString());
			Map<String,Object> map = element.getProperties();
			Set<String> set = map.keySet();
			Iterator<String> iterator = set.iterator();
			String string;
		  while(iterator.hasNext()) {
		  	string = iterator.next();
		  	System.err.println(string + " = " + map.get(string));
		  }
		}
	}
	public String getUrlAsString(URL url) {
		ArrayList<String> lines = getUrlAsList(url);
		StringBuilder document = new StringBuilder();
		for (String line : lines) {
			document.append(line);
		}
		return document.toString();
	}
	public ArrayList<String> getUrlAsList(URL url) {
		ArrayList<String> lines = new ArrayList<String>();
		try {
			//URL url = new URL("http://www.example.com/atom.xml");
			BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
			String line;
			while ((line = reader.readLine()) != null) {
				//document.append(line);
				lines.add(line);
			}
			reader.close();
		}
		catch (MalformedURLException e) {
			return null;
		}
		catch (IOException e) {
			return null;
		}
		return lines;
	}
	public List<String> queryXMLDocument (String url, List<String> queries) {
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		docFactory.setNamespaceAware(true); // never forget this!
		DocumentBuilder builder = null;
		Document doc = null;
		List<String> results = new ArrayList<String>();
    try {
	    builder = docFactory.newDocumentBuilder();
    } catch (ParserConfigurationException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
    }
		try {
	    doc = builder.parse(url);
    } catch (SAXException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
    } catch (IOException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
    }
    XPath xpath = new org.apache.xpath.jaxp.XPathFactoryImpl().newXPath();
    class myNamespaceContext implements NamespaceContext {

    	public void setDocument(Document newdoc) { mydoc = newdoc; }
    	private Document mydoc;
      public String getNamespaceURI(String prefix) {
        return new PrefixResolverDefault(mydoc.getDocumentElement()).getNamespaceForPrefix(prefix);
      }

			@Override
      public String getPrefix(String namespaceURI) {
	      // TODO Auto-generated method stub
	      return null;
      }

			@Override
      public Iterator getPrefixes(String namespaceURI) {
	      // TODO Auto-generated method stub
	      return null;
      }
    };
    myNamespaceContext ctx = new myNamespaceContext();
    ctx.setDocument(doc);
    xpath.setNamespaceContext(ctx);
    for (String query : queries) {
    	XPathExpression path = null;
    	try {
    		path = xpath.compile(query);
    	}
      catch (XPathExpressionException e) {
  	    // TODO Auto-generated catch block
  	    e.printStackTrace();
      }
      String result = null;
      try {
  	    result = path.evaluate(doc);
      }
      catch (XPathExpressionException e) {
  	    // TODO Auto-generated catch block
  	    e.printStackTrace();
      }
      System.err.println("Result: " + result);
      results.add(result);
    }
    return results;
	}
	public String AmazonSearch (String query) {
		StringBuilder result = new StringBuilder();
		// URL url;
		String[] keywords = query.split("\\s+", 2);
		String searchURL = "http://ecs.amazonaws.com/onca/xml?" +
		  "Service=AWSECommerceService&" +
		  "Operation=ItemSearch&" +
		  "AWSAccessKeyId=AKIAJJKM5EKCKIORQEOQ&" +
		  "AssociateTag=goowavlinrob-20&" +
		  "SearchIndex=" + URLUTF8Encoder.encode(keywords[0]) + "&" +
		  "Keywords=" + URLUTF8Encoder.encode(keywords[1]); // + "&" +
		  //"ResponseGroup=Images";
		System.err.println(searchURL);
		/*try {
			url = new URL(urlText);
		}
		catch (MalformedURLException e) {
			System.err.println(e);
			return null;
		} */
		List<String> queries = new ArrayList<String>();
		queries.add("//:ASIN");
		queries.add("//:DetailPageURL");
		queries.add("//:Title");
		List<String> results = queryXMLDocument(searchURL, queries);
		String ASIN = results.get(0);
		String DetailPageURL = results.get(1);
		String Title = results.get(2);
    //XPathFactory XPFactory = XPathFactory.newInstance();
		//XPath xpath = XPFactory.newXPath();

		String iconSearchURL = "http://ecs.amazonaws.com/onca/xml?" +
	  "Service=AWSECommerceService&" +
	  "Operation=ItemLookup&" +
	  "AWSAccessKeyId=AKIAJJKM5EKCKIORQEOQ&" +
	  "AssociateTag=goowavlinrob-20&" +
	  "ItemId=" + ASIN + "&" + 
	  "ResponseGroup=Images";
	  System.err.println(iconSearchURL);
	  queries.clear();
	  queries.add("//:Item/:SmallImage/:URL");
	  results = queryXMLDocument(iconSearchURL, queries);
	  String imgURL = results.get(0);
	  /*
	  try {
	    doc = builder.parse(iconSearchURL);
    } catch (SAXException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
    } catch (IOException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
    }
	  ctx.setDocument(doc);
    xpath.setNamespaceContext(ctx);
    XPathExpression thumbnailPath = null;
    
    try {
    	thumbnailPath = xpath.compile("//:Item/:SmallImage/:URL");
    }
    catch (XPathExpressionException e) {
    	e.printStackTrace();
    }
		String imgURL = null;
		try {
			imgURL = thumbnailPath.evaluate(doc);
		}
		catch
		(XPathExpressionException e) {
			e.printStackTrace();
		}
		*/
		return "<a href=\"" + DetailPageURL + "\">" + Title + "<br /><img src=\"" + imgURL + "\"></img></a>";
  	//System.err.println("Fetching URL " + url);
		//String response = getUrlAsString(url);
		//Pattern detailPagePattern = Pattern.compile("<DetailPageURL>([^<>]+)</DetailPageURL>");
		//Matcher detailPageMatcher = detailPagePattern.matcher(response);
		//if (detailPageMatcher.find()) {
		//	return detailPageMatcher.group(1);
    /*
		Pattern imagePattern = Pattern.compile("<SmallImage><URL>([^<>]+)</URL>");
		Matcher imageMatcher = imagePattern.matcher(response);
		if (imageMatcher.find()) {
			return "<img src=\"" + imageMatcher.group(1) + "\"></img>";
		}
		else {
			return "";
		}
		*/
	}
	public String WoWHeadSearch (String query) {
		StringBuilder result = new StringBuilder();
	  Pattern linkPattern = Pattern.compile("<link>([^<]+)</link>");
		Pattern iconPattern = Pattern.compile("<icon displayId=\"\\d+\">([^<]+)</icon>");
		Pattern qualityPattern = Pattern.compile("<quality id=\"(\\d+)\">");
		Matcher iconMatcher;
		Matcher linkMatcher;
		Matcher qualityMatcher;
		String xml;
		URL url;
		String urlText = searchURLprefix + URLUTF8Encoder.encode(query) + searchURLsuffix;
		String link = "";
		try {
	    url = new URL(urlText);
    } catch (MalformedURLException e) {
    	System.err.println(e);
	    // TODO Auto-generated catch block
	    //e.printStackTrace();
    	return null;
    }
		xml = getUrlAsString(url);
		int quality;
		String qualityColor = "#000000";
		qualityMatcher = qualityPattern.matcher(xml);
		if (qualityMatcher.find()) {
			quality = Integer.parseInt(qualityMatcher.group(1));
			switch (quality) {
      case 1:
        qualityColor = "#FF0000";
        break;
      case 2:
      	qualityColor = "#00FF00";
      	break;
      case 3:
      	qualityColor = "#0000FF";
      default:
        break;
      }
		}
		linkMatcher = linkPattern.matcher(xml);
		if (linkMatcher.find()) {
			link = linkMatcher.group(1);
			//Range range = new Range(start_indices.get(i), end_indices.get(i));
			//textView.delete(range);
			//textView.setAnnotation(range, "link/auto", link);
			// delete brackets
			//textView.replace(new Range(end_indices.get(i)-1, end_indices.get(i)),">");
			//textView.replace(new Range(start_indices.get(i), start_indices.get(i)+1),"<");
		}
		else {
			System.err.println("linkMatcher.find() failed. '" + xml+"' with url'" + urlText + "'");
		}
		iconMatcher = iconPattern.matcher(xml);
		if (iconMatcher.find()) {
			String match = iconMatcher.group(1).toLowerCase();
			//textView.insert(start_indices.get(i)+1, " ");
			//textView.insertElement(start_indices.get(i)+1, new Image("http://static.wowhead.com/images/icons/small/" + match + ".jpg", 18, 18, ""));
			//textView.appendElement(new Image("http://static.wowhead.com/images/icons/small/" + match + ".jpg", 56, 56, ""));
		  result.append("<a href=\"" + link + "\">" + query + "<br /><img height=\"56\" width=\"56\" src=\"http://static.wowhead.com/images/icons/large/" + match + ".jpg\" alt=\"\"></img></a>");
		}
		else {
			//bracketMatcher.appendReplacement(textBuffer, "xmlMatcher.find() failed. '" + xml+"' with url '" + urlText + "'");
			System.err.println("iconMatcher.find() failed. '" + xml+"' with url '" + urlText + "'");
		}
		//bracketMatcher.appendTail(textBuffer);
		//textView.replace(textBuffer.toString());
		return result.toString();
	}
//}
//catch (Exception e1) {
	// TODO Auto-generated catch block
	//e1.printStackTrace();
//	System.err.println(e1.toString()+" on URL " + urlText);
//}
	@Override
	public void processEvents(RobotMessageBundle bundle) {
		System.err.println("beginning of processEvents");
		System.err.println("Debug");
		for (Event e : bundle.getBlipSubmittedEvents()) {
			if (e.getType() == EventType.BLIP_SUBMITTED) {
				Blip blip = e.getBlip();
				//dumpAnnotations(blip);
				TextView textView = blip.getDocument();
				String blipContent = textView.getText();
				//String[] blipLines = blipContent.split("\n");
				//Pattern bracketPattern = Pattern.compile("\\[([^\\[\\]]+)\\]");
				Pattern commandPattern = Pattern.compile("^/search\\s+(.+)$", java.util.regex.Pattern.CASE_INSENSITIVE | java.util.regex.Pattern.MULTILINE);
				Matcher commandMatcher = commandPattern.matcher(blipContent);
				String[] arguments;
				if (commandMatcher.find()) {
				  System.err.println("Found command match on " + commandMatcher.group());
					arguments = commandMatcher.group(1).split("\\s+", 2);
					System.err.println("arguments = " + arguments.toString());
					String engine = arguments[0].toLowerCase(); 
					if (engine.equals("wowhead")) {
						textView.delete(new Range(commandMatcher.start(), commandMatcher.end()));
						textView.append(WoWHeadSearch(arguments[1]));
					}
					else if (engine.equals("amazon")) {
						textView.delete(new Range(commandMatcher.start(), commandMatcher.end()));
						textView.append(AmazonSearch(arguments[1]));
					}
					else {
						System.err.println(arguments[0] + " isn't a search engine I know about");
					}
				}
				else {
					System.err.println("Did not find command match");
				}
				//StringBuffer textBuffer = new StringBuffer();
				//StringBuffer xmlBuffer = new StringBuffer();
				//Matcher bracketMatcher = bracketPattern.matcher(blipLines[blipLines.length - 1]);
				//ArrayList<Integer> start_indices = new ArrayList<Integer>();
				//ArrayList<Integer> end_indices = new ArrayList<Integer>();
				//ArrayList<String> item_texts = new ArrayList<String>();
 				//try {
					//while(bracketMatcher.find()) {
					//	start_indices.add(bracketMatcher.start());
					//	end_indices.add(bracketMatcher.end());
					//	item_texts.add(bracketMatcher.group(1));
					//}
					//for(int i = start_indices.size() - 1; i >= 0; i--) {
						//String itemText = item_texts.get(i);
			}
		}
		System.err.println("end of processEvents");
	}
}
